package com.shb.jutils.commons;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 创建人：shenbing
 * 创建日期：2015-10-29
 * 说明：日期工具类
 * Created by shenbing on 2015/10/29 0029.
 */
public class DateUtil {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    private static final SimpleDateFormat cnDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
    private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
    private static final SimpleDateFormat cnTimeFormat = new SimpleDateFormat("HH点mm分ss秒");
    private static final SimpleDateFormat longDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat cnLongDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH点mm分ss秒");

    /**
     * 私有化构造函数
     */
    private DateUtil(){
    }

    /**
     * 返回当前日期格式化字符串：yyyy-MM-dd
     * @return
     */
    public static String getCurrentDate(){
        return dateFormat.format(new Date());
    }

    /**
     * 返回当前日期和时间格式化字符串：yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String getCurrentTime(){
        return longDateFormat.format(new Date());
    }

    /**
     * 日期格式化：yyyy-MM-dd
     * @param date
     * @return
     */
    public static String formatDate(Date date){
        return dateFormat.format(date);
    }

    /**
     * 日期格式化：yyyy年MM月dd日
     * @param date
     * @return
     */
    public static String formatCnDate(Date date){
        return cnDateFormat.format(new Date());
    }

    /**
     * 时间格式化：HH:mm:ss
     * @param date
     * @return
     */
    public static String formatTime(Date date){
        return timeFormat.format(date);
    }

    /**
     * 时间格式化：HH点mm分ss秒
     * @param date
     * @return
     */
    public static String formatCnTime(Date date){
        return cnTimeFormat.format(date);
    }

    /**
     * 日期和时间格式化：yyyy-MM-dd HH:mm:ss
     * @param date
     * @return
     */
    public static String formatLongDate(Date date){
        return longDateFormat.format(date);
    }

    /**
     * 日期和时间格式化：yyyy年MM月dd日 HH点mm分ss秒
     * @param date
     * @return
     */
    public static String formatCnLongDate(Date date){
        return cnLongDateFormat.format(date);
    }

    /**
     * 按指定的字符串格式化日期返回字符串
     * @param date
     * @param format
     * @return
     */
    public static String format(Date date, String format){
        SimpleDateFormat fmt = new SimpleDateFormat(format);
        return fmt.format(date);
    }

    /**
     * 按照制定的字符串解析日期字符串返回Date
     * @param dateStr
     * @param format
     * @return
     */
    public static Date parse(String dateStr, String format) {
        Date date = null;
        try{
            SimpleDateFormat fmt = new SimpleDateFormat(format);
            date = fmt.parse(dateStr);
        }catch (ParseException e){
            throw new RuntimeException(e);
        }
        return date;
    }

    public static Date parse(String dateStr, String... formats) {
        if (formats == null || formats.length == 0) {
            throw new IllegalArgumentException("Formats can not be null or empty");
        }
        for (String format : formats) {
            try {
                return parse(dateStr, format);
            } catch (Exception e) {
                // ignore
            }
        }
        throw new IllegalArgumentException("Can not parse date string " + dateStr);
    }

    /**
     * 指定的日期加减天数
     * @param date
     * @param days
     * @return
     */
    public static Date addDays(Date date, int days){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE,days);
        return cal.getTime();
    }

    /**
     * 指定的日期加减月数
     * @param date
     * @param months
     * @return
     */
    public static Date addMonths(Date date, int months){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH,months);
        return cal.getTime();
    }

    /**
     * 指定的日期加减年数
     * @param date
     * @param years
     * @return
     */
    public static Date addYears(Date date, int years){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR,years);
        return cal.getTime();
    }

    /**
     * 指定的日期加减分钟
     * @param date
     * @param minutes
     * @return
     */
    public static Date addMinutes(Date date, int minutes){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE,minutes);
        return cal.getTime();
    }

    /**
     * 指定的日期加减秒
     * @param date
     * @param seconds
     * @return
     */
    public static Date addSeconds(Date date, int seconds){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.SECOND,seconds);
        return cal.getTime();
    }

    /**
     * 指定的日期加减毫秒
     * @param date
     * @param millis
     * @return
     */
    public static Date addMillis(Date date, int millis){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MILLISECOND,millis);
        return cal.getTime();
    }

    /**
     * 计算date日期所在的周一，该方法将每周日算作星期的最后一天
     * 即中国式计算方法
     * @param date
     * @return
     */
    public static Date getNowWeekMonDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, -1);    //解决周日会出现并到下一周的情况
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTime();
    }

    /**
     * 计算date日期所在的上周一，该方法将每周日算作星期的最后一天
     * 即中国式计算方法
     * @param date
     * @return
     */
    public static Date getLastWeekMonday(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, -1);    //解决周日会出现并到下一周的情况
        cal.add(Calendar.WEEK_OF_YEAR, -1);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTime();
    }

    /**
     * 计算date日期所在的上周日，该方法将每周日所做星期的最后一天
     * 即中国式计算方法
     * @param date
     * @return
     */
    public static Date getLastWeekSunday(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, -1);    //解决周日会出现并到下一周的情况
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return cal.getTime();
    }

    /**
     * 计算date日期所在星期的第一天（星期日）
     * @param date
     * @return
     */
    public static Date getNowWeekFirstDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return cal.getTime();
    }

    /**
     * 计算date日期的上个星期的第一天（星期日）
     * @param date
     * @return
     */
    public static Date getLastWeekFirstDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
        return cal.getTime();
    }

    /**
     * 计算date日期的上个星期的最后一天（星期六）
     * @param date
     * @return
     */
    public static Date getLastWeekLastDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.WEEK_OF_YEAR, -1);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
        return cal.getTime();
    }

    /**
     * 计算date所在月的第一天
     * @param date
     * @return
     */
    public static Date getNowMonthFirstDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    /**
     * 计算date的上个月的第一天
     * @param date
     * @return
     */
    public static Date getLastMonthFirstDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, -1);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    /**
     * 计算date的上个月的最后一天
     * @param date
     * @return
     */
    public static Date getLastMonthLastDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, -1);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    /**
     * 返回给定日期是"星期X"
     * @param date
     * @return
     */
    public static String getWeekDay(Date date){
        SimpleDateFormat fmt = new SimpleDateFormat("E");
        return fmt.format(date);
    }

    /**
     * 获得给定日期是改年的第几周
     * @param date
     * @return
     */
    public static int getWeekOfYear(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 获得给定日期的月份
     * @param date
     * @return
     */
    public static int geCurrentMonth(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MONTH)+1;
    }

    /**
     * 返回给定日期是该年的第几天
     * @param date
     * @return
     */
    public static int getDayOfYear(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_YEAR);
    }

    /**
     * 计算两日期差的天数，不包括开始日期和结束日期
     * @param date1
     * @param date2
     * @return
     */
    public static long getDiffDays(Date date1, Date date2){
        long diff = date1.getTime() - date2.getTime();
        long days = diff/(1000 * 60 * 60 * 24);
        return days < 0 ? days*(-1)  : days;
    }

    /**
     * 判断日期是否相同
     * @param date1
     * @param date2
     * @return
     */
    public static boolean equalsDate(Date date1, Date date2){
        return DateUtil.formatDate(date1).equals(DateUtil.formatDate(date2));
    }

    /**
     * 判断日期和时间是否相同
     * @param date1
     * @param date2
     * @return
     */
    public static boolean equalsTime(Date date1, Date date2){
        return date1.equals(date2);
    }

    /**
     * 判断date1是否大于date2
     * @param date1
     * @param date2
     * @return
     */
    public static boolean after(Date date1, Date date2){
        return date1.after(date2);
    }

    /**
     * 判断date1是否小于date2
     * @param date1
     * @param date2
     * @return
     */
    public static boolean before(Date date1, Date date2){
        return date1.before(date2);
    }

    /**
     * 得到日期的0点0分0秒对象
     * @param date
     * @return
     */
    public static Date getBeginOfDay(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static void main(String[] args){
        System.out.println(DateUtil.formatLongDate(DateUtil.parse("2015-10-11", "yyyy-MM-dd")));
        System.out.println(DateUtil.getDiffDays(DateUtil.parse("2015-10-03","yyyy-MM-dd"), new Date()));
        Date d1 = DateUtil.parse("2011-11-12","yyyy-MM-dd");
        Date d2 = DateUtil.parse("2011/11/15","yyyy/MM/dd");
        System.out.println(DateUtil.before(d1, d2));
    }
}
